學習程式語言有時會遇到一些非常難理解的觀念,而閉包與裝飾器絕對算是初學者很難跨過的坎,幸運的是,逃避並不可恥,即便不太清楚其中的運作細節,知道怎麼用就足以解決大部分的問題,不過今天有幸參與鐵人賽,我們可以試著搞懂看看,如果還是不懂,希望一年後還有機會再來搞懂一次(笑)。
(明天才會寫裝飾器)
所謂**閉包(Closure)**指的是「允許內部函式訪問外部函式的變數」,淺白一點地說,在一些狀況下,如果某個函式裡面又有一個函數,而最內層的函式需要一個變數,這時候函式會透過先前記住創建當時的上下程式碼,來找可以使用的變數,即使在它所在的外部函式已經執行完畢後,內部函式依然能夠使用外部函式中的變數。
當一個函式(內部函式)在另一個函式(外部函式)內被定義,並且這個內部函式「捕捉」並保存了外部函式中的變數,這種情況就稱為閉包。
所以內部函式將外部作用域的變數「封閉」在它自己的環境中,這就是為什麼閉包會稱作「閉包」。
上面這串說明可能還是有點複雜,所以我們也透過程式碼來感受一下閉包是什麼?
範例:
def add_ten():
ten = 10
def add(num):
return num + ten
return add
closure_result = add_ten()
print(closure_result(5)) # 15
print(closure_result(10)) # 20
我們可以發現在上述的程式碼中,在函式 add_ten
裡面,有變數 ten
與函式 add(num)
,再往更深層看看函式 add(num)
中還有什麼?
在 add(num)
裡面,可以發現接受一個 num
的參數,並有一個 ten
的變數,此時我們尚不知 ten
變數裡面有什麼。
接著程式碼將變數 closure_result
賦予 add_ten()
返回的值,也就是 add
,所以我們可以得知 closure_result
就變成了 add
。
然後讓我們試著進行 closure_result(5)
的運算,剛剛有說了,closure_result
可以替換成 add
,closure_result(5)
也就變成了 add(5)
,而這會返回 5 + ten
,但由於 add(num)
裡面本身沒有 ten
這個變數,所以 Python 因為閉包的特性,會找到外層的 ten = 10
,代表 5 + ten
會變成 5 + 10
,也就會得到最後的結果 15
。